<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2022/12/29
 * Time: 10:11
 */
namespace app\index\service;

use think\Exception;
use think\facade\Cache;
use think\facade\Log;

class KsOpenService{

    private $baseUrl;
    private $appId;
    private $appsecret;
    private $token;//Token(令牌)
    private $salt;//SALT


    public function __construct(){
        $config=config('system.ksDeveloper');
        $this->appId=$config['appid'];//应用id
        $this->appsecret=$config['appsecret'];
    }


    /**
     * 获取token
     * @return mixed
     * @throws Exception
     */
    public function getAccessToken(){
        //首先从缓存中
        $token = Cache::get('ksAccessToken-'.$this->appId);
        if(empty($token)){
            $param['app_id'] = $this->appId;
            $param['app_secret'] = $this->appsecret;
            $param['grant_type'] = 'client_credentials';
            $result = http_post('https://open.kuaishou.com/oauth2/access_token',$param);
            $result = json_decode($result,true);
            if($result['result'] !== 1){
                throw new Exception($result['error_msg'],$result['result']);
            }
            $token = $result['access_token'];
            Cache::set('ksAccessToken-'.$this->appId,$token,5000);
        }
        return $token;
    }



    /**
     * 登录解析
     * @param $code
     * @return mixed
     * @throws Exception
     */
    public function login($code){
        $param['app_id'] = $this->appId;
        $param['app_secret'] = $this->appsecret;
        $param['js_code'] = $code;
        $result = http_post('https://open.kuaishou.com/oauth2/mp/code2session',$param);
        $result = json_decode($result,true);
        if($result['result'] !== 1){
            throw new Exception($result['error_msg'],$result['result']);
        }
        return $result;
    }


    /**
     * 获取快手手机号
     * @param $code
     * @param $encryptedData
     * @param $iv
     * @return string
     * @throws Exception
     */
    public function getPhone($code,$encryptedData,$iv){
        $param['app_id'] = $this->appId;
        $param['app_secret'] = $this->appsecret;
        $param['js_code'] = $code;
        $result = http_post('https://open.kuaishou.com/oauth2/mp/code2session',$param);
        $result = json_decode($result,true);
        if($result['result'] !== 1){
            throw new Exception($result['error_msg'],$result['result']);
        }
        $key = $result['session_key'];
        //解密数据
        $phone = openssl_decrypt(base64_decode($encryptedData,true), 'AES-128-CBC', base64_decode($key), OPENSSL_RAW_DATA, base64_decode($iv));
        if (!$phone){
            throw new Exception('手机号信息解密失败',0);
        }else{
            $phone = json_decode($phone,true)['phoneNumber'];
            $result['phoneNumber'] = $phone;
            return $result;
        }
    }


    /**
     * 快手生成预支付订单
     * @param $order_no
     * @param $open_id
     * @param $total_amount
     * @param $subject
     * @param $detail
     * @param $notify_url
     * @return mixed
     * @throws Exception
     */
    public function createOrder($order_no,$open_id,$total_amount,$subject,$detail,$notify_url){
        $app_id = $this->appId;
        $access_token = $this->getAccessToken();
        $param['app_id'] = $this->appId;
        $param['out_order_no'] = $order_no;
        $param['open_id'] = $open_id;
        $param['total_amount'] = round($total_amount*100,2);
        $param['subject'] = $subject;//商品描述。 长度限制不超过 128 字节且不超过 42 字符
        $param['detail'] = $detail;//商品详情 长度限制不超过 128 字节且不超过 42 字符
        $param['type'] = 1297;
        $param['expire_time'] = 900;//过期时间，即15分钟1297
        $param['notify_url'] = $notify_url;//回调地址
        $sign = $this->getSign($param);
        $param['sign'] = $sign;//生成的签名
        $result = http_post_json("https://open.kuaishou.com/openapi/mp/developer/epay/create_order?app_id={$app_id}&access_token={$access_token}",$param);
        $result = json_decode($result,true);
        if($result['result'] !== 1){
            throw new Exception($result['error_msg'],$result['result']);
        }
        return $result['order_info'];
    }




    /**
     * 推送订单到快手
     * @param $openid
     * @param $out_trade_no
     * @param $order_id
     * @param $create_time
     * @param $total_price
     * @param $title
     * @return mixed
     * @throws Exception
     */
    //https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/server/ecpay/order/order-sync
    public function pushOrder($openid,$out_trade_no,$order_id,$create_time,$total_price,$title){

    }


    /**
     * 退款
     * @param $order_no
     * @param $out_refund_no
     * @param $reason
     * @param $refund_amount
     * @return mixed
     * @throws Exception
     */
    public function createRefund($order_no,$out_refund_no,$reason,$refund_amount){
        $param['app_id'] = $this->appId;
        $param['out_order_no'] = $order_no;//订单号
        $param['out_refund_no'] = $out_refund_no;//商户分配退款号，保证在商户中唯一
        $param['reason'] = $reason;//退款原因
        $param['refund_amount'] = $refund_amount*100;//退款金额
        $sign = $this->getSign($param);
        $param['sign'] = $sign;//生成的签名
        $result = http_post_json('https://developer.toutiao.com/api/apps/ecpay/v1/create_refund',$param);
        $result = json_decode($result,true);
        if($result['err_no'] !== 0){
            throw new Exception($result['err_tips'],$result['err_no']);
        }
        return $result['refund_no'];
    }


    /**
     * 生成支付签名（请求支付接口的签名）
     * @param $map
     * @return string
     */
    private function getSign($map) {
        $rList = array();
        foreach($map as $k =>$v) {
            if ($k == "sign" || $k == "access_token")
                continue;
            array_push($rList, $k);
        }
        sort($rList, 2);
        $map1 = [];
        foreach ($rList as $k=>$v){
            $map1[] = $v.'='.$map[$v];
        }
        $str = implode('&', $map1);
        $str = $str . $this->appsecret;
        return md5($str);
    }


    /**
     * 获取回调的签名
     * @param array $body
     * @param string $token
     * @return string
     */
    public function getNotifySign($body){
        $body = json_encode($body,JSON_UNESCAPED_UNICODE);
        $str = $body.$this->appsecret;
        return md5($str);
    }
}